package FC.KNN;

// Classe para implementar o algoritmo dos k-listaVizinhos mais próximos
import br.com.lacibMusic.entidades.Pontuacao;
import br.com.lacibMusic.rn.PontuacaoRN;
import java.util.List;

// apenas suporta atributos nominais
public class KNN {

    public static int[] converterPontuacaoExemplo(Pontuacao pon) {
        int[] vetor = new int[11];
        vetor[0] = pon.getRock();
        vetor[1] = pon.getJazz();
        vetor[2] = pon.getLatin();
        vetor[3] = pon.getHardcore();
        vetor[4] = pon.getPop();
        vetor[5] = pon.getCountry();
        vetor[6] = pon.getBlues();
        vetor[7] = pon.getFolk();
        vetor[8] = pon.getHiphop();
        vetor[9] = pon.getReb();
        vetor[10] = pon.getEletronic();

        return vetor;
    }
    // Conjunto de dados original
    //ConjuntoDados cd = null;
    private static int[][] cdn;

    public static String individuoToString(int[] linha) {
        String unidade = "";
        for (int i = 0; i < linha.length; i++) {
            if (linha.length - 1 == i) {
                unidade += linha[i];
            } else {
                unidade += linha[i] + "";
            }
        }
        return unidade;
    }
    // Parãmetro k
    int k;

    public KNN() // construtor vazio - assume k = 1
    {
        this(1);
    }

    public KNN(int k) {
        // construtor - necessita valor de k
        this.k = k;
    }

    public int similaridade(int[] ex1, int[] ex2) {
        // calcula similaridade entre dois exemplos
        int res = 0;
        for (int i = 0; i < ex1.length; i++) {
            if (ex1[i] == ex2[i]) {
                res++;
            }
        }
        return res;
    }

    public int[] construirListaVizinhos(int[] ex) {
        // constroi uma lista com os k vizinhos mais proximos de um exemplo 
        int[] vizinhos = new int[this.k]; // lista de vizinhos
        int[] sims = new int[this.k]; // lista de similaridades
        int minsim = ex.length; // valor mais alto possivel
        int minindex = 0;
        for (int i = 0; i < this.k; i++) { // coloca os primeiros k exemplos
            vizinhos[i] = i;
            sims[i] = similaridade(ex, cdn[i]);
            if (sims[i] < minsim) {
                minsim = sims[i];
                minindex = i;
            }
        }

        for (int i = k; i < cdn.length; i++) {
            int s = similaridade(ex, cdn[i]);
            if (s > minsim) { // substitui o menor dos que estavam por um melhor
                vizinhos[minindex] = i;
                sims[minindex] = s;
                // recalcula o minimo
                minsim = sims[0];
                minindex = 0;
                for (int j = 1; j < k; j++) {
                    if (sims[j] < minsim) {
                        minsim = sims[j];
                        minindex = j;
                    }
                }
            }
        }
        return vizinhos;
    }

    public static void main(String[] args) {
        KNN knn = new KNN(3);
        String[] valor = knn.kVizinhosProximos(3, 3);
        for (int i = 0; i < 3; i++) {
            System.out.println("Valor: " + valor[i]);
        }
    }

    public String[] kVizinhosProximos(int kn, int idPontuacao) {
        KNN knn = new KNN(kn);
        List<Pontuacao> valores = new PontuacaoRN().obterTodos();
        Pontuacao pon = new PontuacaoRN().obter(idPontuacao);
        valores.remove(pon);
        int[] linha = converterPontuacaoExemplo(pon);
        System.out.println("");
        cdn = new int[valores.size()][11];
        for (int i = 0; i < valores.size(); i++) {
            cdn[i] = converterPontuacaoExemplo(valores.get(i));
        }

//        for (int i = 0; i < cdn.length; i++) {
//            System.out.print("cdn[" + i + "]: ");
//            for (int j = 0; j < 10; j++) {
//                System.out.print(cdn[i][j] + ", ");
//                
//            }
//            System.out.println("");
//        }

        int[] resultado = knn.construirListaVizinhos(linha);
        String[] result = new String[kn];

        for (int i = 0; i < kn; i++) {
            result[i] = individuoToString(cdn[resultado[i]]);
        }
        return result;
    }
}